﻿using System;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Microsoft.SqlServer.Server;

namespace DataCenter.Share
{
    public static class Utils
    {
        public const int UNREAL_FLAG = 1;
        public const int REAL_FLAG = 2;
        public static DateTime TODAY = DateTime.Today;
        public static DateTime NOW = GetFormatedTime(DateTime.Now);
        public static DateTime EMPTY_TIME = new DateTime(1900, 1, 1);        

        public static byte[] Serialize(object obj)
        {
            byte[] buffer = null;
            if (obj != null)
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(ms, obj);
                    buffer = ms.ToArray();
                }
            }
            return buffer;
        }
        public static object Deserialize(byte[] buffer)
        {
            return Deserialize<object>(buffer);
        }
        public static T Deserialize<T>(byte[] buffer)
        {
            T obj = default(T);
            if (buffer != null && buffer.Length > 0)
            {
                using (MemoryStream ms = new MemoryStream(buffer))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    obj = (T)formatter.Deserialize(ms);
                }
            }
            return obj;
        }
        public static object Clone(object obj)
        {
            byte[] buffer = Serialize(obj);
            return Deserialize(buffer);
        }
        public static T Clone<T>(object obj)
        {
            byte[] buffer = Serialize(obj);
            return Deserialize<T>(buffer);
        }

        public static DateTime GetLastTime(DateTime time)
        {
            return new DateTime(time.Year, time.Month, time.Day, 23, 59, 59);
        }
        public static DateTime GetFormatedTime(DateTime time)
        {
            return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, 0);
        }
        public static bool IsLastTime(DateTime time)
        {
            return ((time.Hour == 23 && time.Minute == 59));
        }
        public static bool IsFirstTime(DateTime time)
        {
            return (time == time.Date);
        }

        public static int[] ConvertStringToArray(string str)
        {
            if (string.IsNullOrEmpty(str)) return null;
            string[] arrStr = str.Split(new char[] { ',', (char)0x1 }, StringSplitOptions.RemoveEmptyEntries);
            int[] arrInt = Array.ConvertAll<string, int>(arrStr,
                delegate(string value)
                {
                    int iValue;
                    if (!int.TryParse(value, out iValue))
                        throw new InvalidCastException("无法将数据\"" + value + "\"转换为整形。");
                    return iValue;
                });
            return arrInt;
        }
        public static string ArrayToString(Array array)
        {
            StringBuilder builder = new StringBuilder();
            foreach (object value in array)
            {
                builder.Append(",");
                builder.Append(value);
            }
            if (builder.Length == 0)
                return "";
            return builder.ToString().Substring(1);
        }

        public static int CallApp(string filePath, string args)
        {
            if (!File.Exists(filePath))
                throw new FileNotFoundException("找不到可执行文件\"" + filePath + "\"");

            ProcessStartInfo startInfo = new ProcessStartInfo(filePath);
            startInfo.CreateNoWindow = true;
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            if (!string.IsNullOrEmpty(args))
                startInfo.Arguments = args;

            Stopwatch watch = new Stopwatch();
            watch.Start();

            Process process = Process.Start(startInfo);
            if (SqlContext.IsAvailable)
            {
                while (!process.StandardOutput.EndOfStream)
                {
                    string input = process.StandardOutput.ReadLine();
                    SqlContext.Pipe.Send(input);
                }
            }
            process.WaitForExit();
            int exitCode = process.ExitCode;
            process.Close();

            watch.Stop();
            SqlContext.Pipe.Send("CallApp: " + watch.ElapsedMilliseconds);

            return exitCode;
        }        

        public static T GetReaderValue<T>(IDataReader reader, string fieldName)
        {
            if (!IsFieldExist(reader, fieldName))
                throw new IndexOutOfRangeException("找不到指定列名\"" + fieldName + "\"");
            object oValue = reader[fieldName];
            return ConvertTo<T>(oValue);
        }
        public static bool IsFieldExist(IDataReader reader, string fieldName)
        {
            for (int i = 0; i < reader.FieldCount; i++)
            {
                if (string.Compare(reader.GetName(i), fieldName, true) == 0)
                    return true;
            }
            return false;
        }
        public static T ConvertTo<T>(object value)
        {
            return (T)ConvertTo(value, typeof(T));
        }
        public static object ConvertTo(object value, Type convertType)
        {
            if (value == null || value == DBNull.Value)
            {
                return null;
            }
            else if (convertType.BaseType == typeof(Enum))
            {
                if (Enum.IsDefined(convertType, value))
                {
                    int iValue;
                    if (!int.TryParse(value.ToString(), out iValue))
                        return Enum.Parse(convertType, value.ToString());
                    else return Enum.ToObject(convertType, value);
                }
            }
            return Convert.ChangeType(value, convertType);
        }
    }
}
